package com.zm.factory;

import com.zm.domain.account;
import com.zm.services.IAcountServices;
import com.zm.utils.TransactionManager;

import javax.annotation.Resource;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//用于创建services的代理对象的工厂
public class BeanFactory {

    //用来存储代理后的对象，具体要代理对象由ioc容器注入
    private IAcountServices acountServices;

    //注入事务管理工具类
    private TransactionManager transactionManager;

    public void  setAcountServices(IAcountServices acountServices) {
        this.acountServices = acountServices;
    }

    /**
     * 获取services代理对象
     * @return
     */
    public IAcountServices getAcountServices() {
        //一定要将代理完的对象返回回去

        //1.代理对象的类加载器
        //2.被代理对象的实现的接口，从中获取代理对象的要被代理的方法
        //3.具体实现代理的匿名内部类，重写其中的invoke方法
        return (IAcountServices) Proxy.newProxyInstance(acountServices.getClass().getClassLoader()
                , acountServices.getClass().getInterfaces()
                , new InvocationHandler() {
                    //添加代理对象的代理逻辑
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object retObj;
                        try {
                            //开启事务
                            transactionManager.beginTransation();
                            //执行代理对象中的被代理方法
                            retObj = method.invoke(acountServices, args);
                            //提交事务
                            transactionManager.commit();
                            //将被代理的方法原逻辑返回回去
                            return retObj;
                        } catch (Exception e) {
                            //如果出现异常回滚事务
                            System.out.println("异常 !!!!!");
                            transactionManager.rollback();
                            throw new RuntimeException(e);
                        } finally {
                            //关闭当前线程的事务连接并且将连接与线程断开
                            transactionManager.removeConn();
                        }

                    }
                });
    }


    public void setTransactionManager(TransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }
}
